﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MathLab.Messaging;

namespace MathLab.Utils
{
  class MatrixDet
  {
    /// <summary>
    /// Count determinant from 3 by 3 dimension matrix by Sarrus method
    /// </summary>
    /// <param name="matrix3x3"></param>
    /// <returns>determinant of 3 by 3 matrix</returns>
    public static double SarrusDet(double[,] matrix3x3)
    {
      if ((3 == matrix3x3.GetLength(0)) && (3 == matrix3x3.GetLength(1)))
      {
        return (matrix3x3[0, 0] * matrix3x3[1, 1] * matrix3x3[2, 2]) + (matrix3x3[0, 1] * matrix3x3[1, 2] * matrix3x3[2, 0]) + (matrix3x3[0, 2] * matrix3x3[1, 0] * matrix3x3[2, 1]) - (matrix3x3[0, 2] * matrix3x3[1, 1] * matrix3x3[2, 0]) - (matrix3x3[0, 1] * matrix3x3[1, 0] * matrix3x3[2, 2]) - (matrix3x3[0, 0] * matrix3x3[1, 2] * matrix3x3[2, 1]);
      }
      else
      {
        throw new Exception("This matrix is not proper to Sarrus Method: Matrix 3x3 needed");
      }
    }
    /// <summary>
    /// Creating a complement matrix - new matrix without values from row x and column y
    /// </summary>
    /// <param name="matrix">base matrix</param>
    /// <param name="x">which row will be deleted</param>
    /// <param name="y">which column will be deleted</param>
    /// <returns>complement matrix</returns>
    public static double[,] ComplementMatrix(double[,] matrix, int x, int y)
    {
      if ((1 == matrix.GetLength(0)) || (1 == matrix.GetLength(1)))
      {
        throw new Exception("Could not create complementary matrix from 1x1 matrix");
      }
      else
      {
        double[,] resultMatrix = new double[(matrix.GetLength(0) - 1), (matrix.GetLength(1) - 1)];

        for (int i = 0; i < matrix.GetLength(0); i++)
        {
          for (int j = 0; j < matrix.GetLength(1); j++)
          {
            if (i == x || j == y)
            {
              continue;
            }
            int rowNr = i;
            int colNr = j;
            if (i > x)
            {
              rowNr = i - 1;
            }
            if (j > y)
            {
              colNr = j - 1;
            }
            resultMatrix[rowNr, colNr] = matrix[i, j];
          }
        }
        return resultMatrix;
      }
    }
    /// <summary>
    /// Count determinant from given matrix
    /// </summary>
    /// <param name="matrix"></param>
    /// <returns>determinant of matrix</returns>
    public static double Determinant(double[,] matrix)
    {
      if (MatrixCorrectness.IsSquaredMatrix(matrix))
      {
        if (1 == matrix.GetLength(0))
        {
          return matrix[0, 0];
        }

        if (2 == matrix.GetLength(0))
        {
          return ((matrix[0, 0] * matrix[1, 1]) - (matrix[1, 0] * matrix[0, 1]));
        }
        if (3 == matrix.GetLength(0))
        {
          return SarrusDet(matrix);
        }
        double result = 0;
        int j = 0;
        for (int i = 0; i < matrix.GetLength(0); i++)
        {
          double tempVal = 0;

          double[,] CompMatrix = ComplementMatrix(matrix, i, j);
          if (3 <= CompMatrix.GetLength(0))
          {
            tempVal = Math.Pow((-1), (i + j)) * matrix[i, j] * Determinant(CompMatrix);
          }
          result += tempVal;
        }
        return result;
      }
      else
      {
        throw new Exception("Could not count determinant: Need squared matrix");
      }
    }
  }
}
